import random
from datetime import datetime
from time import timezone

from django.views.decorators.http import require_http_methods
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from django.contrib.auth.hashers import make_password,check_password
from user.models import User
from user.serializers import UserSerializers, UserTaskStatisticsSerializer
from django_redis import get_redis_connection  # 获取数据库连接,默认获取配置的默认连接
from redis import Redis

# 发送邮件 库
from django.core.mail import EmailMessage


# Create your views here.


class UserView(ModelViewSet):
    # 通用API 必须提供这两个方法
    queryset = User.objects.all()
    serializer_class = UserSerializers

    # 设置权限 ,登录允许任何人访问
    permission_classes = [AllowAny]

    #分页
    pagination_class = PageNumberPagination
    PageNumberPagination.page_size_query_param = 'rows'

    #查询学生列表
    def list(self,request,*args, **kwargs):
        queryset = self.get_queryset().filter(is_active=True,is_staff = False).order_by('id')
        #进行分页
        pagination = self.paginate_queryset(queryset)
        if pagination is None:
            return Response(data = {"message":"请求必须进行分页操作"},status=status.HTTP_400_BAD_REQUEST)
        #对分页后的结果进行序列化
        serializer = self.get_serializer(pagination, many=True)
        #返回分页后的结果
        return self.get_paginated_response(serializer.data)

    # 重写创建对象的方法
    def create(self, request, *args, **kwargs):
        # 判断账号是否已经被注册
        queryset = self.get_queryset().filter(username=request.data['username'])
        if queryset:
            # 提示账号已被注册
            return Response(data={"message": '账户已被注册'}, status=status.HTTP_404_NOT_FOUND)
        # 如果有值,则提示已被注册,如果没有值,调用父类的创建方法,进行创建用户
        return super().create(request, *args, **kwargs)

    # 根据邮箱获取验证码
    @action(methods=['GET'], detail=False, url_path='code-email', url_name='code-email')
    def get_code_by_email(self, request, *args, **kwargs):
        # 获取传入的邮箱
        email = request.query_params.get('email')
        if email is None:
            return Response(data={"message": "邮箱不允许为空"}, status=status.HTTP_400_BAD_REQUEST)

        # 查询数据库该账户是否存在
        queryset = self.get_queryset().filter(username=email, is_staff=False)
        if not queryset:
            return Response(data={"message": "邮箱找不到"}, status=status.HTTP_400_BAD_REQUEST)

        # 生成验证码,并发送邮箱
        random_code = "".join(random.choices("0123456789", k=6))
        # 验证码存入到redis 中,获取 redis 连接
        redis_client: Redis = get_redis_connection()
        # 将验证码存储到redis 中
        redis_client.setex(f"{email}", 5 * 60, random_code)

        user = queryset[0]
        # 邮箱内容
        content = f"""
<p>尊敬的<b>{user.first_name}{user.last_name}</b></p>，

您好！

感谢您使用[任务管理系统]！

为了保障您的账户安全，我们刚刚为您生成了一个一次性验证码，用于验证您的身份或完成某项操作。

<p>您的验证码是：[<b style='font-size:30px'>{random_code}</b>]</p>

验证码用途：[简要说明验证码的用途，例如：重置密码、绑定手机、登录验证等]

验证码有效期：[验证码的有效时间为:5分钟]

请注意，验证码是一次性的，并且只在指定时间内有效。如果验证码过期，您将需要重新请求一个新的验证码。

为了您的账户安全，请不要将验证码泄露给任何人。如果您没有请求验证码，或者怀疑您的账户安全受到威胁，请立即联系我们的客服团队，我们将尽快为您提供帮助。

如果您在输入验证码时遇到问题，或者需要进一步的帮助，请随时通过以下方式与我们联系：

客服邮箱：[您的客服邮箱地址]
客服热线：[您的客服电话]
在线客服：[提供在线客服链接，如果适用]
我们非常重视您的账户安全，并致力于为您提供最优质的服务。如果您有任何疑问或建议，请随时与我们联系。

感谢您的理解和支持！
        """
        # 发送验证码邮件
        message = EmailMessage("任务管理系统-找回密码", body=content, to=(email,))
        print(message)
        # 将内容以网页形式发送
        message.content_subtype = "html"
        # 发送验证码邮件
        message.send()
        return Response(status=status.HTTP_200_OK)

    #找回密码
    @action(methods=['POST'],detail=False,url_name='handleActions',url_path='handleActions')
    def handleActions_pad(self,request,*args,**kwargs):
        data=request.data #从前端获取数据
        email=data.get('email')
        # 将验证码从redis 中取出,获取 redis 连接
        redis_client: Redis = get_redis_connection()
        #从redis中获取邮箱验证码
        code=redis_client.get(email).decode('utf-8') #将从redis 中取出来的验证码(取出来是字符串流)进行转换
        if code == data.get('code'):
            #密码进行修改
            user=User.objects.get(username=data.get('email'))
            user.set_password(data.get('password'))  # 设置新的密码
            user.save()
            return Response(data={"message":"密码修改成功"},status=status.HTTP_200_OK)
        return Response(data={"message":"您的验证码不正确"},status=status.HTTP_200_OK)


    # 修改用户密码
    @action(methods=['post'], detail=False, url_name='update-Pwd', url_path='update-Pwd')
    def update_pwd(self, request, *args, **kwargs):
        user_id = request.user.id  # 获取token中用户id
        oldpwd = request.data.get('oldPassword')  # 用户的旧密码
        newpwd = request.data.get('password')  #用户新的密码
        user=User.objects.get(id=user_id)
        if not check_password(oldpwd,user.password):
            return Response(status=status.HTTP_404_NOT_FOUND)
        user.set_password(newpwd)   #设置新的密码
        user.save()
        return Response(data={"message":"密码修改成功"},status=status.HTTP_200_OK)

    # 用户注册获取验证码
    @action(methods=['GET'], detail=False, url_path='register-code-email', url_name='register-code-email')
    def get_code_by_email_to_register(self, request, *args, **kwargs):
        # 获取传入的邮箱
        email = request.query_params.get('email')
        if email is None:
            return Response(data={"message": "邮箱不允许为空"}, status=status.HTTP_400_BAD_REQUEST)
        # 生成验证码,并发送邮箱
        random_code = "".join(random.choices("0123456789", k=6))
        # 验证码存入到redis 中,获取 redis 连接
        redis_client: Redis = get_redis_connection()
        # 将验证码存储到redis 中
        redis_client.setex(f"{email}", 5 * 60, random_code)

        user = email
        # 邮箱内容
        content = f"""
    <p>尊敬的<b>新用户</b></p>，

    您好！

    感谢您使用[任务管理系统]！

    为了保障您的账户安全，我们刚刚为您生成了一个一次性验证码，用于验证您的身份或完成某项操作。

    <p>您的验证码是：[<b style='font-size:30px'>{random_code}</b>]</p>

    验证码用途：[简要说明验证码的用途，例如：重置密码、绑定手机、登录验证等]

    验证码有效期：[验证码的有效时间为:5分钟]

    请注意，验证码是一次性的，并且只在指定时间内有效。如果验证码过期，您将需要重新请求一个新的验证码。

    为了您的账户安全，请不要将验证码泄露给任何人。如果您没有请求验证码，或者怀疑您的账户安全受到威胁，请立即联系我们的客服团队，我们将尽快为您提供帮助。

    如果您在输入验证码时遇到问题，或者需要进一步的帮助，请随时通过以下方式与我们联系：

    客服邮箱：[您的客服邮箱地址]
    客服热线：[您的客服电话]
    在线客服：[提供在线客服链接，如果适用]
    我们非常重视您的账户安全，并致力于为您提供最优质的服务。如果您有任何疑问或建议，请随时与我们联系。

    感谢您的理解和支持！
            """
        # 发送验证码邮件
        message = EmailMessage("任务管理系统-用户注册", body=content, to=(email,))
        print(message)
        # 将内容以网页形式发送
        message.content_subtype = "html"
        # 发送验证码邮件
        message.send()
        return Response(status=status.HTTP_200_OK)

    @action(methods=['DELETE'],detail=False,url_path='disable-user',url_name='disable-user')
    def DisableUsers(self, request, *args, **kwargs):
        # 禁用用户
        url = request.path
        id = request.query_params.get('id') #获取被禁用用户id
        user = self.get_queryset().get(id=id,is_staff=False)
        if user:
            user.is_active = False
            user.update_time = datetime.now()
            user.save()
            return Response(data={"message": f'禁用用户 {user.first_name+user.last_name} 成功'}, status=status.HTTP_200_OK)
        return Response(data={"message": "删除失败"}, status=status.HTTP_400_BAD_REQUEST)



    @action(methods=['PUT'],detail=False,url_name='reset-password',url_path='reset-password')
    def Resetpassword(self,request, *args, **kwargs):
        # 重置密码
        id = request.query_params.get('id') #获取被重置用户id
        user=self.get_queryset().get(id=id,is_staff=False) #获取需要重置密码的用户
        password = '000000' #设置新密码
        if user:
            user.set_password(password)  # 设置新的密码
            user.save()
            return Response(data={"message": f'重置密码成功,用户 {user.first_name + user.last_name} 成功,密码是: {password}'},
                            status=status.HTTP_200_OK)
        return Response(data={"message": "重置密码失败"}, status=status.HTTP_400_BAD_REQUEST)




class UserTaskHub(viewsets.ModelViewSet):
    queryset = User.objects.filter(is_staff=False, is_active=True)
    serializer_class = UserTaskStatisticsSerializer
    #保留 list 方法不变，因为它现在会使用新的序列化器来序列化数据

    # 分页
    # pagination_class = PageNumberPagination
    PageNumberPagination.page_size_query_param = 'rows'

